package com.jourwon.spring.boot.controller;

import com.jourwon.spring.boot.annotation.Mobile;
import com.jourwon.spring.boot.model.entity.User;
import com.jourwon.spring.boot.model.vo.CommonResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.Map;

/**
 * 表单请求
 *
 * @author JourWon
 * @date 2022/1/19
 */
@Api(tags = "表单请求")
@RestController
@Validated
@RequestMapping("/form")
public class FormController {

    /**
     * 后端用实体类接收
     * 在方法上使用@Valid或者@Validated注解都能对user对象的参数进行校验
     * 但是如果把@Valid或者@Validated注解放到类上面，而方法不添加这两个注解，是不会进行校验的
     * <p>
     * 前端则调用url：
     * "http://localhost:8080/form/getByUser?age=18&createTime=2022-01-01%2000:00:00&deleteState=0
     * &email=zhangsan@163.com&mobilePhoneNumber=13800000000&password=123456&updateTime=2022-01-01%2000:00:00
     * &userId=1&username=%E5%BC%A0%E4%B8%89"
     * <p>
     * 如果参数绑定失败，则会报BindException异常，比如createTime字段绑定失败
     * LocalDateTime类型字段不添加DateTimeFormat注解，前端传来的字符串时间转换为LocalDateTime会报[BindException] 参数绑定失败
     * Failed to convert property value of type 'java.lang.String'
     * to required type 'java.time.LocalDateTime' for property 'createTime'
     *
     * @param user
     * @return
     */
    @GetMapping("/getByUser")
    @ApiOperation("后端用实体类接收")
    public CommonResponse<User> getByUser(@Validated User user) {
        return CommonResponse.success(user);
    }

    /**
     * 后端用参数接收,自定义注解校验
     * 在方法或者类上添加@Validated注解
     *
     * @param mobile
     * @return
     */
    @GetMapping("/getByAnnotation")
    @ApiOperation("后端用参数接收,自定义注解校验")
    public CommonResponse<User> getByAnnotation(@Validated @Mobile String mobile) {
        return CommonResponse.success(new User(mobile, 18));
    }

    /**
     * 后端用参数接收
     * 前端则调用url：localhost:8080/form/getByParam?name1=tom
     * 后端用参数接收，参数验证 @Validated 注解加在接口类上
     *
     * @param name
     * @param age
     * @return
     */
    @GetMapping("/getByParam")
    @ApiOperation("后端用参数接收")
    public CommonResponse<User> getByParam(@RequestParam("name1") @NotBlank(message = "用户名不能为空") String name,
                                           @RequestParam(value = "age", required = true)
                                           @Max(value = 120, message = "年龄最大为120") @Min(value = 1, message = "年龄最小为1") int age) {
        return CommonResponse.success(new User(name, age));
    }

    /**
     * 后端用Map接收
     * 前端则调用url：localhost:8080/form/getByMap?name=tom&age=12
     * map参数前需要加@RequestParam注解，用于将请求参数注入到map中
     *
     * @param map
     * @return
     */
    @GetMapping("/getByMap")
    @ApiOperation("后端用Map接收")
    public CommonResponse<User> getByMap(@RequestParam Map<String, Object> map) {
        String name = (String) map.get("name");
        int age = Integer.parseInt((String) map.get("age"));
        return CommonResponse.success(new User(name, age));
    }

    /**
     * 后端用路径接收
     * 前端则调用url：localhost:8080/form/getByPath/tom/12
     * PathVariable注解用于将路径中的参数绑定到方法参数中
     *
     * @param name
     * @param age
     * @return
     */
    @GetMapping("/getByPath/{name}/{age}")
    @ApiOperation("后端用路径接收")
    public CommonResponse<User> getByPath(@PathVariable("name") String name, @PathVariable("age") int age) {
        return CommonResponse.success(new User(name, age));
    }

    /**
     * 后端用数组接收
     * 前端则调用url：localhost:8080/form/array?a=1&a=2&a=3
     *
     * @param a
     * @return
     */
    @GetMapping("/array")
    @ApiOperation("后端用数组接收")
    public CommonResponse<Integer[]> array(Integer[] a) {
        return CommonResponse.success(a);
    }

    /**
     * 后端用列表接收
     * 前端则调用url：localhost:8080/form/list?a=1&a=2&a=3
     * 当然，这里也可用List<Integer>来接收，不过需要加上@RequestParam("a")注解
     * 如果直接使用List<Integer>来接收，也不加上@RequestParam("a")注解的话，则会报错
     * IllegalStateException: No primary or single public constructor found for interface java.util.List
     * - and no default constructor found either
     *
     * @param a
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("后端用列表接收")
    public CommonResponse<List<Integer>> list(@RequestParam("a") List<Integer> a) {
        return CommonResponse.success(a);
    }

}
